package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.GroundSign;
import com.myk.game.gobangchess.signs.TitleSign;


/**
 * 数字五子棋
 */
public class DigitGoBang extends Room{
    public DigitGoBang(String roomName) {
        super(roomName, "五子棋，但有些格子不值钱。日出设计。","数字五子棋", BoardStyleData.getGoBangStyle(15,15), true, true);
    }

    private int[][] valueBoard=new int[15][15];     //每个格子开局随机的价值
    private int[][] pointBoard=new int[15][15];     //每个格子(棋子)的实际得分
    private int[][] directionLock=new int[15][15];  //N连不可被加长

    private static final int multiRate = 10; //N连分数相乘比率
    private static final int initScore = 18; //后手初始补偿分
    private static final int winScore = 200;//胜利分

    public final int[] dirx={-1,-1,0,1}, diry={0,1,1,1}; //直斜共4个方向 ←↖↑↗

    @Override
    public String getRuleText() {
        return  "双方轮流落子。\n" + "棋子得分等于棋盘上写的数字。\n" +
                "参与N连(N>=5)的棋子分数乘"+multiRate+"；在多个方向参与N连的棋子得分累加。\n" +
                "N连一经形成，不再被延长。\n"+
                "后手开局有"+initScore+"分补偿。得到"+winScore+"分获胜。";
    }
    @Override
    protected void onStartPrepare() {
        resetGrids();
        noticeBlackMove();
    }

    @Override
    public void resetGrids() {
        super.resetGrids();

        int cards[]=new int[225],randIndex,swapTmp;
        for(int i=0;i<75;i++){
            cards[i]=1; cards[i+75]=2; cards[i+150]=3;
        }
        do{
            for(int i=224;i>0;i--){
                randIndex=(int)(Math.random()*(i+1));
                swapTmp=cards[i];
                cards[i]=cards[randIndex];
                cards[randIndex]=swapTmp;
            }
            for(int i=0;i<15;i++) //棋盘相关的数字初始化
                for(int j=0;j<15;j++)
                    valueBoard[i][j]=cards[i*15+j];
        }while(checkLongChain());

        whiteScore=initScore;
        blackScore=0;
        for(int i=0;i<15;i++) //棋盘相关的数字初始化
            for(int j=0;j<15;j++) {
                pointBoard[i][j]=valueBoard[i][j];
                curGrids[i][j]=directionLock[i][j]=0;
            }
        for(int i=0;i<15;i++) //数字填充
            for(int j=0;j<15;j++)
                signList.add(new TitleSign((j+0.5f)/15,(i+0.45f)/15,0,Integer.toString(pointBoard[i][j]),"#995F5558",0.5f));
    }

    private boolean checkLongChain(){
        boolean flag=false;
        int x,y,cnt[]=new int[4];
        for(int i=3;i<12;i++){
            for(int j=3;j<12;j++){
                for(int d=0;d<4;d++){
                    cnt[1]=cnt[2]=cnt[3]=0; x=i; y=j;
                    for(int k=0;k<5;k++){
                        if(x<3||x>11||y<3||y>11) break;
                        cnt[valueBoard[x][y]]++;
                        if(cnt[1]+cnt[2]>=2 && cnt[2]+cnt[3]>=2) break;
                        x+=dirx[d]; y+=diry[d];
                    }
                    if(cnt[1]>=4||cnt[3]>=4){
                        flag=true; break;
                    }
                }
                if(flag) break;
            }
            if(flag) break;
        }
        return flag;
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (curGrids[row][col]==0){ //只能落在空位置
            curGrids[row][col]=value; //实际落子
            scoring(row,col,value);
            signList.add(new GroundSign(getIndex(row,col),"#00000000","#9900FF00",1.3f));
            stepAdd();
            if(whiteScore>=winScore) {
                doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
                return ;
            }
            if(blackScore>=winScore) {
                doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
                return ;
            }
            //不会发生棋盘填满和棋，因为填满总共有450分，至少一方已经拿到200分了。
            if(value==1) noticeWhiteMove();
            else noticeBlackMove();
        }
    }

    public void scoring(int row,int col,int value){
        int l1,l2,x,y;
        for(int d=0;d<4;d++){
            l1=0; x=row; y=col;
            do{
                x+=dirx[d]; y+=diry[d];
                if(x>14||x<0||y>14||y<0) break;
                if(curGrids[x][y]!=value) break;
                if((directionLock[x][y]>>d)%2==1) break; //这个棋子在这个方向已经参与过N连了
                l1++;
            }while(true);
            l2=0; x=row; y=col;
            do{
                x-=dirx[d]; y-=diry[d];
                if(x>14||x<0||y>14||y<0) break;
                if(curGrids[x][y]!=value) break;
                if((directionLock[x][y]>>d)%2==1) break; //这个棋子在这个方向已经参与过N连了
                l2++;
            }while(true);
            if(l1+l2<4) continue;

            x=row; y=col;
            for(int i=0;i<l1+1;i++){ //原位也在此更新
                if(pointBoard[x][y]<4) pointBoard[x][y]*=multiRate;
                else pointBoard[x][y]+=(valueBoard[x][y]*multiRate);
                directionLock[x][y]+=(1<<d);
                x+=dirx[d]; y+=diry[d];
            }
            x=row; y=col;
            for(int i=0;i<l2;i++){
                x-=dirx[d]; y-=diry[d];
                if(pointBoard[x][y]<4) pointBoard[x][y]*=multiRate;
                else pointBoard[x][y]+=(valueBoard[x][y]*multiRate);
                directionLock[x][y]+=(1<<d);
            }
        }
        signList.clear();
        int newScore=0;
        for(int i=0;i<15;i++)
            for(int j=0;j<15;j++){
                if(curGrids[i][j]==1)
                    signList.add(new TitleSign((j+0.5f)/15,(i+0.45f)/15,0,Integer.toString(pointBoard[i][j]),"#FF33FFBB",0.5f));
                else if(curGrids[i][j]==2)
                    signList.add(new TitleSign((j+0.5f)/15,(i+0.45f)/15,0,Integer.toString(pointBoard[i][j]),"#FFFF33BB",0.5f));
                else
                    signList.add(new TitleSign((j+0.5f)/15,(i+0.45f)/15,0,Integer.toString(pointBoard[i][j]),"#995F5558",0.5f));
                if(curGrids[i][j]==value)
                    newScore+=pointBoard[i][j];
            }
        if(value==1) blackScore=newScore;
        else whiteScore=newScore+initScore;
    }
}
